package com.hzdesk.media.koreabatchmatvector.custom;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.view.View;

import com.hzdesk.media.koreabatchmatvector.bean.DcfBean;
import com.hzdesk.media.koreabatchmatvector.bean.MouseUserDevicesinfoBean;
import com.hzdesk.media.koreabatchmatvector.bean.PathBean;
import com.hzdesk.media.koreabatchmatvector.bean.SerPath;
import com.hzdesk.media.koreabatchmatvector.bean.SerPoint;
import com.hzdesk.media.koreabatchmatvector.bean.XmlUserBean;
import com.hzdesk.media.koreabatchmatvector.bean.XmlVideoFile;
import com.hzdesk.media.koreabatchmatvector.config.AppConfig;
import com.hzdesk.media.koreabatchmatvector.dao.MouseUserDevicesinfoDaoUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Timer;

/**
 * Created by Administrator on 2018/6/22.
 */

public class SecondCanvas extends View {
    private String TAG = SecondCanvas.class.getSimpleName();
    private Canvas mCanvas;
    private Bitmap bitmap;
    private DcfBean mBean;
    private Paint mPaint;
    public Timer mTimer;
    private List<PathBean> mList;
    private long currentTime = 0;
    private long startTime = 0;                   //开始时间
    private List<Bean> SecondAllStack;          //绘制图形总栈
    private List<Bean> SecondUndoStack;         //绘制中所有执行Undo的图形
    private List<Bean> SecondRedoStack;         //绘制中所有执行Redo的图形
    private List<Bean> SecondClearStack;        //绘制中所有执行Clear的图形
    private List<Bean> SecondCurrentDrawSrack;  //当前时间点所要展示的图形
    private List<XmlVideoFile> FileList;
    private int currentIndex = 0;
    private boolean isChange = false;
    private Context mContext;
    private List<XmlUserBean> xmlUserBeanList;

    public SecondCanvas(Context context) {
        super(context);
        mContext = context;
        initialize();
    }

    public SecondCanvas(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initialize();
    }

    public SecondCanvas(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initialize();
    }


    private void initialize() {
        bitmap = Bitmap.createBitmap(AppConfig.SCREEN_WIDTH, AppConfig.SCREEN_HIGHR, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas();
        mCanvas.setBitmap(bitmap);
        SecondAllStack = new ArrayList<>();
        SecondUndoStack = new ArrayList<>();
        SecondRedoStack = new ArrayList<>();
        SecondClearStack = new ArrayList<>();
        SecondCurrentDrawSrack = new ArrayList<>();
        FileList = new ArrayList<>();
        mTimer = new Timer();

    }

    //绘制准备
    public void startDraw(DcfBean bean, String name) {
        mBean = bean;
        mList = mBean.getList();
        xmlUserBeanList = bean.getUserList();
        FileList = bean.getFileList();
        boolean state = false;
        //遍历mList 初始化四个栈
        for (PathBean bean1 : mList) {

            if (bean1.getType().equals(AppConfig.PAINT_PENU)) {
                currentIndex++;
                int size = bean1.getmSerPath().mTimes.size();
                long time = bean1.getmSerPath().mTimes.get(size - 1);
                Path path = getPenuPath(bean1.getmSerPath());
                Log.d(TAG, "1:" + time + "");
                SecondAllStack.add(new Bean(path, bean1.getColor(), bean1.getSize(), time, currentIndex, bean1.getNumber()));
            } else if (bean1.getType().equals(AppConfig.PAINT_LINE)) {
                currentIndex++;
                int size = bean1.getmSerPath().mTimes.size();
                long time = bean1.getmSerPath().mTimes.get(size - 1);
                Path path = getLinePath(bean1.getmSerPath());
                Log.d(TAG, "1:" + time + "");
                SecondAllStack.add(new Bean(path, bean1.getColor(), bean1.getSize(), time, currentIndex, bean1.getNumber()));
            } else if (bean1.getType().equals(AppConfig.PAINT_OVAL)) {
                currentIndex++;
                int size = bean1.getmSerPath().mTimes.size();
                long time = bean1.getmSerPath().mTimes.get(size - 1);
                Path path = getOvaluPath(bean1.getmSerPath());
                Log.d(TAG, "1:" + time + "");
                SecondAllStack.add(new Bean(path, bean1.getColor(), bean1.getSize(), time, currentIndex, bean1.getNumber()));
            } else if (bean1.getType().equals(AppConfig.PAINT_RECT)) {
                currentIndex++;
                int size = bean1.getmSerPath().mTimes.size();
                long time = bean1.getmSerPath().mTimes.get(size - 1);
                Path path = getRectuPath(bean1.getmSerPath());
                Log.d(TAG, "1:" + time + "");
                SecondAllStack.add(new Bean(path, bean1.getColor(), bean1.getSize(), time, currentIndex, bean1.getNumber()));
            } else if (bean1.getType().equals(AppConfig.PAINT_UNDO)) {
                //遍历总栈下用户num的绘制路径 取出放在list中

                List<Bean> list = new ArrayList<>();
                for (Bean bean2 : SecondAllStack) {
                    if (bean2.getNum() == bean1.getNumber()) {
                        list.add(bean2);
                    }
                }
                //遍历Redo栈有没有该对象
                Bean bean2 = null;

                for (int i = list.size() - 1; i > 0; i--) {
                    bean2 = list.get(i);
                    boolean has = false;
                    for (Bean bean3 : SecondRedoStack) {
                        if (bean3.getIndex() == bean2.getIndex()) {
                            SecondUndoStack.add(new Bean(bean1.getTime(), bean2.getIndex(), bean1.getNumber()));
                            has = true;
                            break;
                        }
                    }
                    if (has) {
                        break;
                    }
                    if (!has) {
                        SecondUndoStack.add(new Bean(bean1.getTime(), bean2.getIndex(), bean1.getNumber()));
                        break;
                    }
                }
                list.clear();
            } else if (bean1.getType().equals(AppConfig.PAINT_REDO)) {
                //遍历Undo栈 查找该用户的绘制路径
                List<Bean> list = new ArrayList<>();
                for (Bean bean2 : SecondUndoStack) {
                    if (bean2.getNum() == bean1.getNumber()) {
                        list.add(bean2);
                    }
                }

                Bean bean2 = list.get(list.size() - 1);
                SecondRedoStack.add(new Bean(bean1.getTime(), bean2.getIndex(), bean1.getNumber()));


            } else if (bean1.getType().equals(AppConfig.PAINT_CLEAR)) {
                SecondClearStack.add(new Bean(bean1.getTime(), currentIndex, bean1.getNumber()));
            }

        }
        //开始时间
        for (XmlVideoFile xmlVideoFile : FileList) {
            if (xmlVideoFile.getName().equals(name)) {
                startTime = xmlVideoFile.getStartTime();
                break;
            }
        }

        Log.d(TAG, "over:" + currentIndex);
        new MyThread().start();


    }

    public void changeProgress(long time) {
        currentTime = time + startTime;
        isChange = true;

        // mCanvas.restore();
    }

    //显示用户批注
    public void showUserAnnotation(int num) {
        for (int i = 0; i < xmlUserBeanList.size(); i++) {
            if (xmlUserBeanList.get(i).getNumber() == num) {
                xmlUserBeanList.get(i).setIsShow(1);
            }
        }

    }

    //隐藏用户批注
    public void hideUserAnnotation(int num) {
        for (int i = 0; i < xmlUserBeanList.size(); i++) {
            if (xmlUserBeanList.get(i).getNumber() == num) {
                xmlUserBeanList.get(i).setIsShow(0);
            }
        }

    }

    public void showAllUserAnnotation() {
        for (int i = 0; i < xmlUserBeanList.size(); i++) {
            xmlUserBeanList.get(i).setIsShow(1);
        }

    }

    public void hideAllUserAnnotation() {
        for (int i = 0; i < xmlUserBeanList.size(); i++) {
            xmlUserBeanList.get(i).setIsShow(0);
        }

    }


    private class MyThread extends Thread {
        public MyThread() {
        }

        @Override
        public void run() {
            super.run();
            while (true) {
                if (isChange) {
                    isChange = false;
                    //根据时间点初始化三个临时栈
                    List<Pair<Integer, Long>> list_Undo = new ArrayList<>();
                    List<Pair<Integer, Long>> list_Redo = new ArrayList<>();
                    List<Integer> list_Clear = new ArrayList<>();
                    for (Bean bean2 : SecondUndoStack) {
                        if (currentTime >= bean2.getTime()) {
                            list_Undo.add(new Pair<Integer, Long>(bean2.getIndex(), bean2.getTime()));
                        }
                    }
                    for (Bean bean2 : SecondRedoStack) {
                        if (currentTime >= bean2.getTime()) {
                            list_Redo.add(new Pair<Integer, Long>(bean2.getIndex(), bean2.getTime()));
                        }
                    }
                    for (Bean bean2 : SecondClearStack) {
                        if (currentTime >= bean2.getTime()) {
                            list_Clear.add(bean2.getNum());
                        }
                    }
                    SecondCurrentDrawSrack.clear();
                    for (Bean bean2 : SecondAllStack) {
                        if (currentTime >= bean2.getTime()) {
                            boolean isclear = false;
                            boolean isUndo = false;
                            //Undo 后 Redo 清除相同的 注：不能使用增强遍历
                            for (int i = 0; i < list_Undo.size(); i++) {
                                Pair<Integer, Long> pair = list_Undo.get(i);
                                for (Pair<Integer, Long> pair1 : list_Redo) {
                                    if (pair1.first == pair.first) {
                                        list_Undo.remove(pair);
                                        break;
                                    }
                                }
                            }

                            //是否被Undo
                            for (Pair<Integer, Long> pair : list_Undo) {
                                if (bean2.getIndex() == pair.first) {
                                    isUndo = true;
                                    break;
                                }
                            }
                            if (isUndo) {
                                continue;
                            }
                            //是否被清理
                            for (int a : list_Clear) {
                                if (bean2.getNum() == a) {
                                    isclear = true;
                                    break;
                                }
                            }
                            if (isclear) {
                                continue;
                            }
                            SecondCurrentDrawSrack.add(bean2);
                        }
                    }
                    postInvalidate();
                }

            }

        }
    }


    private void sortList(List<Bean> list) {
        Collections.sort(list, new Comparator<Bean>() {
            @Override
            public int compare(Bean p1, Bean p2) {
                return p1.getIndex() - p2.getIndex();
            }
        });
    }

    private void rePaint() {
        Paint paint = new Paint();
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mCanvas.drawPaint(paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
        postInvalidate();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(bitmap, 0, 0, mPaint);
        super.onDraw(canvas);
        mCanvas.setBitmap(bitmap);
        Paint paint = new Paint();
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mCanvas.drawPaint(paint);
        for (int i = 0; i < SecondCurrentDrawSrack.size(); i++) {
            Bean bean2 = SecondCurrentDrawSrack.get(i);
            int num = bean2.getNum();
            //筛选用户
            for (int j = 0; j < xmlUserBeanList.size(); j++) {
                if (xmlUserBeanList.get(j).getNumber() == num) {
                    if (xmlUserBeanList.get(j).getIsShow() == 1) {
                        mCanvas.drawPath(bean2.getPath(), getPaint(bean2.getColor(), bean2.getSize()));
                    } else {
                        break;
                    }
                }

            }

        }

        //Log.d("v2","draw:"+currentTime);


    }


    public Paint getPaint(String color, int size) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setColor(Color.parseColor("#" + color));
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(size);
        return paint;

    }


    private Path getPenuPath(SerPath serPath) {
        Path path = new Path();
        int i = serPath.mPoints.size();
        if (i < 3) {
            return path;
        }
        SerPoint point = serPath.mPoints.get(0);
        path.moveTo(point.x, point.y);
        path.lineTo(point.x, point.y);
        float mX = point.x;
        float mY = point.y;
        for (int j = 1; j < serPath.mPoints.size() - 1; j++) {
            SerPoint point2 = serPath.mPoints.get(j);
            path.quadTo(mX, mY, (point2.x + mX) / 2, (point2.y + mY) / 2);
            path.lineTo(point2.x, point2.y);
            mX = point2.x;
            mY = point2.y;
        }
        SerPoint point2 = serPath.mPoints.get(i - 1);
        path.lineTo(point2.x, point2.y);
        mX = point2.x;
        mY = point2.y;
        return path;
    }

    private Path getLinePath(SerPath serPath) {
        Path path = new Path();
        int size = serPath.mPoints.size();
        SerPoint point = serPath.mPoints.get(0);
        SerPoint point2 = serPath.mPoints.get(size - 1);
        path.moveTo(point.x, point.y);
        path.lineTo(point2.x, point2.y);
        return path;
    }

    private Path getOvaluPath(SerPath serPath) {
        RectF rectf = new RectF();
        int size = serPath.mPoints.size();
        rectf.left = serPath.mPoints.get(0).x;
        rectf.top = serPath.mPoints.get(0).y;
        rectf.right = serPath.mPoints.get(size - 1).x;
        rectf.bottom = serPath.mPoints.get(size - 1).y;
        Path path = new Path();
        path.addOval(rectf, Path.Direction.CW);
        return path;
    }

    private Path getRectuPath(SerPath serPath) {
        int size = serPath.mPoints.size();
        Path path = new Path();
        path.addRect(serPath.mPoints.get(0).x, serPath.mPoints.get(0).y, serPath.mPoints.get(size - 1).x,
                serPath.mPoints.get(size - 1).y, Path.Direction.CW);
        return path;
    }

    private class Bean {
        private Path path;//路径
        private String color;//颜色
        private int size;//笔触大小
        private long time;//时间
        private int index;//路径索引
        private int num;//用户

        public Bean(Path path, String color, int size, long time, int index, int num) {
            this.path = path;
            this.color = color;
            this.size = size;
            this.time = time;
            this.num = num;
            this.index = index;
        }

        public Bean(long time, int index, int num) {
            this.time = time;
            this.index = index;
            this.num = num;
        }

        public Path getPath() {
            return path;
        }

        public void setPath(Path path) {
            this.path = path;
        }

        public String getColor() {
            return color;
        }

        public void setColor(String color) {
            this.color = color;
        }

        public int getSize() {
            return size;
        }

        public void setSize(int size) {
            this.size = size;
        }

        public long getTime() {
            return time;
        }

        public void setTime(long time) {
            this.time = time;
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public int getNum() {
            return num;
        }

        public void setNum(int num) {
            this.num = num;
        }

        @Override
        public String toString() {
            return "Bean{" +
                    "path=" + path +
                    ", color='" + color + '\'' +
                    ", size=" + size +
                    ", time=" + time +
                    ", index=" + index +
                    ", num=" + num +
                    '}';
        }
    }

}
